{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Cython Basics\n",
    "\n",
    "In this example, we demonstrate the basic usage of Cython functionalities. Note that the it is not recommended to run cython code in such a fashion. This is simply for convenient purposes. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext Cython"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# The Cython data type"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Integral types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 -3 1 True\n"
     ]
    }
   ],
   "source": [
    "%%cython\n",
    "\n",
    "cdef:\n",
    "    int i = 0\n",
    "    unsigned long j = 1\n",
    "    signed short k = -3\n",
    "    long long ll = 1LL\n",
    "    bint flag = True #Pay attention to this one.\n",
    "\n",
    "print(i, j, k, ll, flag)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Floating point types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0 -1.0 1e+100\n"
     ]
    }
   ],
   "source": [
    "%%cython\n",
    "\n",
    "cdef:\n",
    "    float a = 1.0\n",
    "    double b = -1.0\n",
    "    long double c = 1e100\n",
    "print(a, b, c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### String types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "asdf b'jkl;'\n"
     ]
    }
   ],
   "source": [
    "%%cython\n",
    "\n",
    "cdef str s = \"asdf\"\n",
    "cdef bytes b = b\"jkl;\"\n",
    "print(s, b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Other statically-declarable Python types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1] {'a': 'b'} {1} frozenset({1}) 2020-12-15 19:34:59.295030 array('i', [1, 2, 3])\n"
     ]
    }
   ],
   "source": [
    "%%cython\n",
    "\n",
    "import datetime\n",
    "cimport cpython.datetime # We'll cover the `cimport` keyword later\n",
    "\n",
    "import array\n",
    "cimport cpython.array\n",
    "\n",
    "cdef:\n",
    "    list lst = [1]\n",
    "    dict dd = {'a': 'b'}\n",
    "    set ss = set([1])\n",
    "    frozenset fs = frozenset([1])\n",
    "    cpython.datetime.datetime dt = datetime.datetime.now()\n",
    "    cpython.array.array aa = array.array('i', [1, 2, 3])\n",
    "    \n",
    "print(lst, dd, ss, fs, dt, aa)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Use C++ Containers\n",
    "\n",
    "There is virtually no libcpp documentations. Therefore the only way to know what is going on is by going to https://github.com/cython/cython/tree/master/Cython/Includes/libcpp."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "%%cython --cplus \n",
    "from libcpp.vector cimport vector\n",
    "\n",
    "cdef vector[int] my_vector\n",
    "my_vector.push_back(1) # This is rather inefficient. Better call .reserve first. \n",
    "my_vector.push_back(2)\n",
    "\n",
    "for i in my_vector:\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cython functions\n",
    "* Cython supports 3 kinds of functions:\n",
    "  * Python `def` functions -- compiled Python functions that work with Python types. (Usually) Doesn't lead to any performance improvement. \n",
    "  * C-level `cdef` functions -- low-overhead C-level functions that support C-only types. Can only be called from within Cython code. \n",
    "  * Hybrid `cpdef` functions -- C-level function with auto-generated Python compatibility wrappers."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `cdef` functions: C-functions with Python-like syntax"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3 ab\n",
      "3 5\n"
     ]
    }
   ],
   "source": [
    "%%cython\n",
    "\n",
    "cdef untyped(a, b):\n",
    "    return a + b\n",
    "\n",
    "print(untyped(1, 2), untyped('a', 'b'))\n",
    "\n",
    "cdef int typed(double a, double b):\n",
    "    return <int>(a + b) # Type casting in Cython.\n",
    "\n",
    "print(typed(1, 2), typed(3.14, 2.72))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `cdef` variables / functions not visible to Python outside defining scope"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'untyped' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-13-0a50bcfc1400>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0muntyped\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtyped\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# This will create an error\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m: name 'untyped' is not defined"
     ]
    }
   ],
   "source": [
    "print(untyped(1, 2), typed(1, 2)) # This will create an error"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### `cpdef` functions: two functions in one!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29.13 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_376bf45efd901d376ba290e124707a09.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       "pre { line-height: 125%; margin: 0; }\n",
       "td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29.13</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-0\">&#xA0;<span class=\"\">1</span>: </pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">2</span>: <span class=\"c\"># cpdef functions are just like cdef functions with</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">3</span>: <span class=\"c\"># an implicitly defined Python wrapper for free.</span></pre>\n",
       "<pre class=\"cython line score-44\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">4</span>: <span class=\"k\">cpdef</span> <span class=\"kt\">int</span> <span class=\"nf\">cpdef_func</span><span class=\"p\">(</span><span class=\"nb\">int</span> <span class=\"n\">y</span><span class=\"p\">,</span> <span class=\"nb\">int</span> <span class=\"n\">z</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-44 '>static PyObject *__pyx_pw_46_cython_magic_376bf45efd901d376ba290e124707a09_1cpdef_func(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
       "static int __pyx_f_46_cython_magic_376bf45efd901d376ba290e124707a09_cpdef_func(int __pyx_v_y, int __pyx_v_z, CYTHON_UNUSED int __pyx_skip_dispatch) {\n",
       "  int __pyx_r;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"cpdef_func\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_376bf45efd901d376ba290e124707a09_1cpdef_func(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
       "static PyObject *__pyx_pw_46_cython_magic_376bf45efd901d376ba290e124707a09_1cpdef_func(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
       "  int __pyx_v_y;\n",
       "  int __pyx_v_z;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"cpdef_func (wrapper)\", 0);\n",
       "  {\n",
       "    static PyObject **__pyx_pyargnames[] = {&amp;__pyx_n_s_y,&amp;__pyx_n_s_z,0};\n",
       "    PyObject* values[2] = {0,0};\n",
       "    if (unlikely(__pyx_kwds)) {\n",
       "      Py_ssize_t kw_args;\n",
       "      const Py_ssize_t pos_args = <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args);\n",
       "      switch (pos_args) {\n",
       "        case  2: values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  1: values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  0: break;\n",
       "        default: goto __pyx_L5_argtuple_error;\n",
       "      }\n",
       "      kw_args = <span class='py_c_api'>PyDict_Size</span>(__pyx_kwds);\n",
       "      switch (pos_args) {\n",
       "        case  0:\n",
       "        if (likely((values[0] = <span class='pyx_c_api'>__Pyx_PyDict_GetItemStr</span>(__pyx_kwds, __pyx_n_s_y)) != 0)) kw_args--;\n",
       "        else goto __pyx_L5_argtuple_error;\n",
       "        CYTHON_FALLTHROUGH;\n",
       "        case  1:\n",
       "        if (likely((values[1] = <span class='pyx_c_api'>__Pyx_PyDict_GetItemStr</span>(__pyx_kwds, __pyx_n_s_z)) != 0)) kw_args--;\n",
       "        else {\n",
       "          <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"cpdef_func\", 1, 2, 2, 1); <span class='error_goto'>__PYX_ERR(0, 4, __pyx_L3_error)</span>\n",
       "        }\n",
       "      }\n",
       "      if (unlikely(kw_args &gt; 0)) {\n",
       "        if (unlikely(<span class='pyx_c_api'>__Pyx_ParseOptionalKeywords</span>(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"cpdef_func\") &lt; 0)) <span class='error_goto'>__PYX_ERR(0, 4, __pyx_L3_error)</span>\n",
       "      }\n",
       "    } else if (<span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args) != 2) {\n",
       "      goto __pyx_L5_argtuple_error;\n",
       "    } else {\n",
       "      values[0] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 0);\n",
       "      values[1] = <span class='py_macro_api'>PyTuple_GET_ITEM</span>(__pyx_args, 1);\n",
       "    }\n",
       "    __pyx_v_y = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(values[0]); if (unlikely((__pyx_v_y == (int)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 4, __pyx_L3_error)</span>\n",
       "    __pyx_v_z = <span class='pyx_c_api'>__Pyx_PyInt_As_int</span>(values[1]); if (unlikely((__pyx_v_z == (int)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 4, __pyx_L3_error)</span>\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L5_argtuple_error:;\n",
       "  <span class='pyx_c_api'>__Pyx_RaiseArgtupleInvalid</span>(\"cpdef_func\", 1, 2, 2, <span class='py_macro_api'>PyTuple_GET_SIZE</span>(__pyx_args)); <span class='error_goto'>__PYX_ERR(0, 4, __pyx_L3_error)</span>\n",
       "  __pyx_L3_error:;\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_376bf45efd901d376ba290e124707a09.cpdef_func\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_376bf45efd901d376ba290e124707a09_cpdef_func(__pyx_self, __pyx_v_y, __pyx_v_z);\n",
       "\n",
       "  /* function exit code */\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_376bf45efd901d376ba290e124707a09_cpdef_func(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_y, int __pyx_v_z) {\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"cpdef_func\", 0);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyInt_From_int</span>(__pyx_f_46_cython_magic_376bf45efd901d376ba290e124707a09_cpdef_func(__pyx_v_y, __pyx_v_z, 0));<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  __pyx_r = __pyx_t_1;\n",
       "  __pyx_t_1 = 0;\n",
       "  goto __pyx_L0;\n",
       "\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_1);\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_376bf45efd901d376ba290e124707a09.cpdef_func\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">5</span>:     <span class=\"k\">return</span> <span class=\"n\">y</span> <span class=\"o\">+</span> <span class=\"n\">z</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_r = (__pyx_v_y + __pyx_v_z);\n",
       "  goto __pyx_L0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">6</span>: </pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">7</span>: <span class=\"c\"># Call directly from other Cython code:</span></pre>\n",
       "<pre class=\"cython line score-6\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">8</span>: <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">cpdef_func</span><span class=\"p\">(</span><span class=\"mf\">1</span><span class=\"p\">,</span> <span class=\"mf\">2</span><span class=\"p\">))</span></pre>\n",
       "<pre class='cython code score-6 '>  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyInt_From_int</span>(__pyx_f_46_cython_magic_376bf45efd901d376ba290e124707a09_cpdef_func(1, 2, 0));<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  __pyx_t_2 = <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_builtin_print, __pyx_t_1);<span class='error_goto'> if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "    \n",
    "# cpdef functions are just like cdef functions with\n",
    "# an implicitly defined Python wrapper for free.\n",
    "cpdef int cpdef_func(int y, int z):\n",
    "    return y + z\n",
    "\n",
    "# Call directly from other Cython code:\n",
    "print(cpdef_func(1, 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cython and NumPy, buffers, fused types\n",
    "\n",
    "We'll be re-implementing the `scipy.stats.poisson.entropy()` function / method using Cython and its NumPy support, and we'll see what sort of speedup we can get for our efforts."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pure Python implementation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "def shannon_entropy_py(p_x):\n",
    "    return - np.sum(p_x * np.log(p_x))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cythonized version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29.13 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_bd2fb9f20576b110750a856f0086ee12.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       "pre { line-height: 125%; margin: 0; }\n",
       "td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29.13</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-0\">&#xA0;<span class=\"\">1</span>: </pre>\n",
       "<pre class=\"cython line score-16\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">2</span>: <span class=\"k\">import</span> <span class=\"nn\">numpy</span> <span class=\"k\">as</span> <span class=\"nn\">np</span></pre>\n",
       "<pre class='cython code score-16 '>  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_Import</span>(__pyx_n_s_numpy, 0, 0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_np, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "/* … */\n",
       "  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyDict_NewPresized</span>(0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_test, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">3</span>: <span class=\"k\">cimport</span> <span class=\"nn\">numpy</span> <span class=\"k\">as</span> <span class=\"nn\">cnp</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">4</span>: </pre>\n",
       "<pre class=\"cython line score-20\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">5</span>: <span class=\"k\">def</span> <span class=\"nf\">shannon_entropy_cy</span><span class=\"p\">(</span><span class=\"n\">cnp</span><span class=\"o\">.</span><span class=\"n\">ndarray</span> <span class=\"n\">p_x</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-20 '>/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_bd2fb9f20576b110750a856f0086ee12_1shannon_entropy_cy(PyObject *__pyx_self, PyObject *__pyx_v_p_x); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_bd2fb9f20576b110750a856f0086ee12_1shannon_entropy_cy = {\"shannon_entropy_cy\", (PyCFunction)__pyx_pw_46_cython_magic_bd2fb9f20576b110750a856f0086ee12_1shannon_entropy_cy, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_bd2fb9f20576b110750a856f0086ee12_1shannon_entropy_cy(PyObject *__pyx_self, PyObject *__pyx_v_p_x) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_cy (wrapper)\", 0);\n",
       "  if (unlikely(!<span class='pyx_c_api'>__Pyx_ArgTypeTest</span>(((PyObject *)__pyx_v_p_x), __pyx_ptype_5numpy_ndarray, 1, \"p_x\", 0))) <span class='error_goto'>__PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_bd2fb9f20576b110750a856f0086ee12_shannon_entropy_cy(__pyx_self, ((PyArrayObject *)__pyx_v_p_x));\n",
       "\n",
       "  /* function exit code */\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_bd2fb9f20576b110750a856f0086ee12_shannon_entropy_cy(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_p_x) {\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_cy\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_1);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_3);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_4);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_5);\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_bd2fb9f20576b110750a856f0086ee12.shannon_entropy_cy\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__8 = <span class='py_c_api'>PyTuple_Pack</span>(1, __pyx_n_s_p_x);<span class='error_goto'> if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple__8);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple__8);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_bd2fb9f20576b110750a856f0086ee12_1shannon_entropy_cy, NULL, __pyx_n_s_cython_magic_bd2fb9f20576b11075);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_shannon_entropy_cy, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-52\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">6</span>:     <span class=\"k\">return</span> <span class=\"o\">-</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">sum</span><span class=\"p\">(</span><span class=\"n\">p_x</span> <span class=\"o\">*</span> <span class=\"n\">np</span><span class=\"o\">.</span><span class=\"n\">log</span><span class=\"p\">(</span><span class=\"n\">p_x</span><span class=\"p\">))</span></pre>\n",
       "<pre class='cython code score-52 '>  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_t_2, __pyx_n_s_np);<span class='error_goto'> if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
       "  __pyx_t_3 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_2, __pyx_n_s_sum);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  <span class='pyx_c_api'>__Pyx_GetModuleGlobalName</span>(__pyx_t_4, __pyx_n_s_np);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
       "  __pyx_t_5 = <span class='pyx_c_api'>__Pyx_PyObject_GetAttrStr</span>(__pyx_t_4, __pyx_n_s_log);<span class='error_goto'> if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
       "  __pyx_t_4 = NULL;\n",
       "  if (CYTHON_UNPACK_METHODS &amp;&amp; unlikely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_5))) {\n",
       "    __pyx_t_4 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_5);\n",
       "    if (likely(__pyx_t_4)) {\n",
       "      PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_5);\n",
       "      <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_4);\n",
       "      <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n",
       "      <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_5, function);\n",
       "    }\n",
       "  }\n",
       "  __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_4, ((PyObject *)__pyx_v_p_x)) : <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_5, ((PyObject *)__pyx_v_p_x));\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
       "  if (unlikely(!__pyx_t_2)) <span class='error_goto'>__PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_2);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
       "  __pyx_t_5 = <span class='py_c_api'>PyNumber_Multiply</span>(((PyObject *)__pyx_v_p_x), __pyx_t_2);<span class='error_goto'> if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_t_2 = NULL;\n",
       "  if (CYTHON_UNPACK_METHODS &amp;&amp; unlikely(<span class='py_c_api'>PyMethod_Check</span>(__pyx_t_3))) {\n",
       "    __pyx_t_2 = <span class='py_macro_api'>PyMethod_GET_SELF</span>(__pyx_t_3);\n",
       "    if (likely(__pyx_t_2)) {\n",
       "      PyObject* function = <span class='py_macro_api'>PyMethod_GET_FUNCTION</span>(__pyx_t_3);\n",
       "      <span class='pyx_macro_api'>__Pyx_INCREF</span>(__pyx_t_2);\n",
       "      <span class='pyx_macro_api'>__Pyx_INCREF</span>(function);\n",
       "      <span class='pyx_macro_api'>__Pyx_DECREF_SET</span>(__pyx_t_3, function);\n",
       "    }\n",
       "  }\n",
       "  __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_t_5) : <span class='pyx_c_api'>__Pyx_PyObject_CallOneArg</span>(__pyx_t_3, __pyx_t_5);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
       "  if (unlikely(!__pyx_t_1)) <span class='error_goto'>__PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __pyx_t_3 = <span class='py_c_api'>PyNumber_Negative</span>(__pyx_t_1);<span class='error_goto'> if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 6, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_3);\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_r = __pyx_t_3;\n",
       "  __pyx_t_3 = 0;\n",
       "  goto __pyx_L0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "\n",
    "import numpy as np\n",
    "cimport numpy as cnp\n",
    "\n",
    "def shannon_entropy_cy(cnp.ndarray p_x):\n",
    "    return - np.sum(p_x * np.log(p_x))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## What's `cimport`?\n",
    "\n",
    "Cython introduces a new keyword, `cimport` that allows interfacing with other Cython code _at the C-level_ and _at compile time_.\n",
    "\n",
    "This is in distinction to Python's regular `import` statement, which interfaces with other _Python_ modules at _runtime_.\n",
    "\n",
    "The statement `cimport numpy as cnp` allows Cython to interface with NumPy arrays at the C level and at compile time for improved performance.\n",
    "\n",
    "The `cimport numpy` statement causes the Cython compiler to look for a `numpy.pxd` Cython declaration file at compile time.  This is where we can find the C-level declarations of the NumPy C-API.  Here we're using the `ndarray` object from `numpy.pxd` to declare the argument of `shannon_entropy_cy()`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Scipy.stats comparison"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.stats import poisson\n",
    "poi = poisson(10.0)\n",
    "n = 100\n",
    "pmf = poi.pmf(np.arange(n))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.5614099352749125\n",
      "2.5614099352749125\n",
      "2.5614099352749125\n"
     ]
    }
   ],
   "source": [
    "print(poi.entropy())\n",
    "print(shannon_entropy_py(pmf))\n",
    "print(shannon_entropy_cy(pmf))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "960 µs ± 27.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "poi.entropy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6.29 µs ± 36 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "shannon_entropy_py(pmf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6.23 µs ± 66.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "shannon_entropy_cy(pmf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29.13 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_804c485fda84e598cb878de00c109dcb.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       "pre { line-height: 125%; margin: 0; }\n",
       "td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29.13</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-0\">&#xA0;<span class=\"\">01</span>: </pre>\n",
       "<pre class=\"cython line score-8\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">02</span>: <span class=\"k\">cimport</span> <span class=\"nn\">numpy</span> <span class=\"k\">as</span> <span class=\"nn\">cnp</span></pre>\n",
       "<pre class='cython code score-8 '>  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyDict_NewPresized</span>(0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_test, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">03</span>: <span class=\"k\">from</span> <span class=\"nn\">libc.math</span> <span class=\"k\">cimport</span> <span class=\"n\">log</span> <span class=\"k\">as</span> <span class=\"n\">clog</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">04</span>: </pre>\n",
       "<pre class=\"cython line score-12\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">05</span>: <span class=\"k\">cpdef</span> <span class=\"nf\">shannon_entropy_v1</span><span class=\"p\">(</span><span class=\"n\">cnp</span><span class=\"o\">.</span><span class=\"n\">ndarray</span> <span class=\"n\">p_x</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-12 '>static PyObject *__pyx_pw_46_cython_magic_804c485fda84e598cb878de00c109dcb_1shannon_entropy_v1(PyObject *__pyx_self, PyObject *__pyx_v_p_x); /*proto*/\n",
       "static PyObject *__pyx_f_46_cython_magic_804c485fda84e598cb878de00c109dcb_shannon_entropy_v1(PyArrayObject *__pyx_v_p_x, CYTHON_UNUSED int __pyx_skip_dispatch) {\n",
       "  double __pyx_v_res;\n",
       "  int __pyx_v_n;\n",
       "  int __pyx_v_i;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_v1\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_4);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_5);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_6);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_8);\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_804c485fda84e598cb878de00c109dcb.shannon_entropy_v1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = 0;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_804c485fda84e598cb878de00c109dcb_1shannon_entropy_v1(PyObject *__pyx_self, PyObject *__pyx_v_p_x); /*proto*/\n",
       "static PyObject *__pyx_pw_46_cython_magic_804c485fda84e598cb878de00c109dcb_1shannon_entropy_v1(PyObject *__pyx_self, PyObject *__pyx_v_p_x) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_v1 (wrapper)\", 0);\n",
       "  if (unlikely(!<span class='pyx_c_api'>__Pyx_ArgTypeTest</span>(((PyObject *)__pyx_v_p_x), __pyx_ptype_5numpy_ndarray, 1, \"p_x\", 0))) <span class='error_goto'>__PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_804c485fda84e598cb878de00c109dcb_shannon_entropy_v1(__pyx_self, ((PyArrayObject *)__pyx_v_p_x));\n",
       "\n",
       "  /* function exit code */\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_804c485fda84e598cb878de00c109dcb_shannon_entropy_v1(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_p_x) {\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_v1\", 0);\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  __pyx_t_1 = __pyx_f_46_cython_magic_804c485fda84e598cb878de00c109dcb_shannon_entropy_v1(__pyx_v_p_x, 0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  __pyx_r = __pyx_t_1;\n",
       "  __pyx_t_1 = 0;\n",
       "  goto __pyx_L0;\n",
       "\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_1);\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_804c485fda84e598cb878de00c109dcb.shannon_entropy_v1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">06</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">double</span> <span class=\"nf\">res</span> <span class=\"o\">=</span> <span class=\"mf\">0.0</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_res = 0.0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">07</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">n</span> <span class=\"o\">=</span> <span class=\"n\">p_x</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_n = (__pyx_v_p_x-&gt;dimensions[0]);\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">08</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">i</span></pre>\n",
       "<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">09</span>:     <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_t_1 = __pyx_v_n;\n",
       "  __pyx_t_2 = __pyx_t_1;\n",
       "  for (__pyx_t_3 = 0; __pyx_t_3 &lt; __pyx_t_2; __pyx_t_3+=1) {\n",
       "    __pyx_v_i = __pyx_t_3;\n",
       "</pre><pre class=\"cython line score-50\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">10</span>:         <span class=\"n\">res</span> <span class=\"o\">+=</span> <span class=\"n\">p_x</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">*</span> <span class=\"n\">clog</span><span class=\"p\">(</span><span class=\"n\">p_x</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">])</span></pre>\n",
       "<pre class='cython code score-50 '>    __pyx_t_4 = <span class='py_c_api'>PyFloat_FromDouble</span>(__pyx_v_res);<span class='error_goto'> if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 10, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_4);\n",
       "    __pyx_t_5 = <span class='pyx_c_api'>__Pyx_GetItemInt</span>(((PyObject *)__pyx_v_p_x), __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 0, 1, 1);<span class='error_goto'> if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 10, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_5);\n",
       "    __pyx_t_6 = <span class='pyx_c_api'>__Pyx_GetItemInt</span>(((PyObject *)__pyx_v_p_x), __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 0, 1, 1);<span class='error_goto'> if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 10, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_6);\n",
       "    __pyx_t_7 = __pyx_<span class='py_c_api'>PyFloat_AsDouble</span>(__pyx_t_6); if (unlikely((__pyx_t_7 == (double)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 10, __pyx_L1_error)</span>\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_6); __pyx_t_6 = 0;\n",
       "    __pyx_t_6 = <span class='py_c_api'>PyFloat_FromDouble</span>(log(__pyx_t_7));<span class='error_goto'> if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 10, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_6);\n",
       "    __pyx_t_8 = <span class='py_c_api'>PyNumber_Multiply</span>(__pyx_t_5, __pyx_t_6);<span class='error_goto'> if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 10, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_8);\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_5); __pyx_t_5 = 0;\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_6); __pyx_t_6 = 0;\n",
       "    __pyx_t_6 = <span class='py_c_api'>PyNumber_InPlaceAdd</span>(__pyx_t_4, __pyx_t_8);<span class='error_goto'> if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 10, __pyx_L1_error)</span>\n",
       "    <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_6);\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_4); __pyx_t_4 = 0;\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_8); __pyx_t_8 = 0;\n",
       "    __pyx_t_7 = __pyx_<span class='py_c_api'>PyFloat_AsDouble</span>(__pyx_t_6); if (unlikely((__pyx_t_7 == (double)-1) &amp;&amp; <span class='py_c_api'>PyErr_Occurred</span>())) <span class='error_goto'>__PYX_ERR(0, 10, __pyx_L1_error)</span>\n",
       "    <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_6); __pyx_t_6 = 0;\n",
       "    __pyx_v_res = __pyx_t_7;\n",
       "  }\n",
       "</pre><pre class=\"cython line score-6\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">11</span>:     <span class=\"k\">return</span> <span class=\"o\">-</span><span class=\"n\">res</span></pre>\n",
       "<pre class='cython code score-6 '>  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  __pyx_t_6 = <span class='py_c_api'>PyFloat_FromDouble</span>((-__pyx_v_res));<span class='error_goto'> if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_6);\n",
       "  __pyx_r = __pyx_t_6;\n",
       "  __pyx_t_6 = 0;\n",
       "  goto __pyx_L0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "\n",
    "cimport numpy as cnp\n",
    "from libc.math cimport log as clog\n",
    "\n",
    "cpdef shannon_entropy_v1(cnp.ndarray p_x):\n",
    "    cdef double res = 0.0\n",
    "    cdef int n = p_x.shape[0]\n",
    "    cdef int i\n",
    "    for i in range(n):\n",
    "        res += p_x[i] * clog(p_x[i])\n",
    "    return -res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "32.2 µs ± 361 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "shannon_entropy_v1(pmf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29.13 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_6f91eb064c6ca682606d401967bf4f38.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       "pre { line-height: 125%; margin: 0; }\n",
       "td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29.13</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-0\">&#xA0;<span class=\"\">01</span>: </pre>\n",
       "<pre class=\"cython line score-8\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">02</span>: <span class=\"k\">cimport</span> <span class=\"nn\">numpy</span> <span class=\"k\">as</span> <span class=\"nn\">cnp</span></pre>\n",
       "<pre class='cython code score-8 '>  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyDict_NewPresized</span>(0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_test, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">03</span>: <span class=\"k\">from</span> <span class=\"nn\">libc.math</span> <span class=\"k\">cimport</span> <span class=\"n\">log</span> <span class=\"k\">as</span> <span class=\"n\">clog</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">04</span>: </pre>\n",
       "<pre class=\"cython line score-26\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">05</span>: <span class=\"k\">def</span> <span class=\"nf\">shannon_entropy_v2</span><span class=\"p\">(</span><span class=\"n\">cnp</span><span class=\"o\">.</span><span class=\"n\">ndarray</span><span class=\"p\">[</span><span class=\"n\">double</span><span class=\"p\">]</span> <span class=\"n\">p_x</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-26 '>/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_6f91eb064c6ca682606d401967bf4f38_1shannon_entropy_v2(PyObject *__pyx_self, PyObject *__pyx_v_p_x); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_6f91eb064c6ca682606d401967bf4f38_1shannon_entropy_v2 = {\"shannon_entropy_v2\", (PyCFunction)__pyx_pw_46_cython_magic_6f91eb064c6ca682606d401967bf4f38_1shannon_entropy_v2, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_6f91eb064c6ca682606d401967bf4f38_1shannon_entropy_v2(PyObject *__pyx_self, PyObject *__pyx_v_p_x) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_v2 (wrapper)\", 0);\n",
       "  if (unlikely(!<span class='pyx_c_api'>__Pyx_ArgTypeTest</span>(((PyObject *)__pyx_v_p_x), __pyx_ptype_5numpy_ndarray, 1, \"p_x\", 0))) <span class='error_goto'>__PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_6f91eb064c6ca682606d401967bf4f38_shannon_entropy_v2(__pyx_self, ((PyArrayObject *)__pyx_v_p_x));\n",
       "\n",
       "  /* function exit code */\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_6f91eb064c6ca682606d401967bf4f38_shannon_entropy_v2(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_p_x) {\n",
       "  double __pyx_v_res;\n",
       "  int __pyx_v_n;\n",
       "  int __pyx_v_i;\n",
       "  __Pyx_LocalBuf_ND __pyx_pybuffernd_p_x;\n",
       "  __Pyx_Buffer __pyx_pybuffer_p_x;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_v2\", 0);\n",
       "  __pyx_pybuffer_p_x.pybuffer.buf = NULL;\n",
       "  __pyx_pybuffer_p_x.refcount = 0;\n",
       "  __pyx_pybuffernd_p_x.data = NULL;\n",
       "  __pyx_pybuffernd_p_x.rcbuffer = &amp;__pyx_pybuffer_p_x;\n",
       "  {\n",
       "    __Pyx_BufFmt_StackElem __pyx_stack[1];\n",
       "    if (unlikely(<span class='pyx_c_api'>__Pyx_GetBufferAndValidate</span>(&amp;__pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer, (PyObject*)__pyx_v_p_x, &amp;__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) <span class='error_goto'>__PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  }\n",
       "  __pyx_pybuffernd_p_x.diminfo[0].strides = __pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer.strides[0]; __pyx_pybuffernd_p_x.diminfo[0].shape = __pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer.shape[0];\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_7);\n",
       "  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;\n",
       "    __Pyx_PyThreadState_declare\n",
       "    __Pyx_PyThreadState_assign\n",
       "    <span class='pyx_c_api'>__Pyx_ErrFetch</span>(&amp;__pyx_type, &amp;__pyx_value, &amp;__pyx_tb);\n",
       "    <span class='pyx_c_api'>__Pyx_SafeReleaseBuffer</span>(&amp;__pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer);\n",
       "  <span class='pyx_c_api'>__Pyx_ErrRestore</span>(__pyx_type, __pyx_value, __pyx_tb);}\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_6f91eb064c6ca682606d401967bf4f38.shannon_entropy_v2\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  goto __pyx_L2;\n",
       "  __pyx_L0:;\n",
       "  <span class='pyx_c_api'>__Pyx_SafeReleaseBuffer</span>(&amp;__pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer);\n",
       "  __pyx_L2:;\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__8 = <span class='py_c_api'>PyTuple_Pack</span>(4, __pyx_n_s_p_x, __pyx_n_s_res, __pyx_n_s_n, __pyx_n_s_i);<span class='error_goto'> if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple__8);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple__8);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_6f91eb064c6ca682606d401967bf4f38_1shannon_entropy_v2, NULL, __pyx_n_s_cython_magic_6f91eb064c6ca68260);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_shannon_entropy_v2, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 5, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">06</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">double</span> <span class=\"nf\">res</span> <span class=\"o\">=</span> <span class=\"mf\">0.0</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_res = 0.0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">07</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">n</span> <span class=\"o\">=</span> <span class=\"n\">p_x</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_n = (__pyx_v_p_x-&gt;dimensions[0]);\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">08</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">i</span></pre>\n",
       "<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">09</span>:     <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_t_1 = __pyx_v_n;\n",
       "  __pyx_t_2 = __pyx_t_1;\n",
       "  for (__pyx_t_3 = 0; __pyx_t_3 &lt; __pyx_t_2; __pyx_t_3+=1) {\n",
       "    __pyx_v_i = __pyx_t_3;\n",
       "</pre><pre class=\"cython line score-4\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">10</span>:         <span class=\"n\">res</span> <span class=\"o\">+=</span> <span class=\"n\">p_x</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">*</span> <span class=\"n\">clog</span><span class=\"p\">(</span><span class=\"n\">p_x</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">])</span></pre>\n",
       "<pre class='cython code score-4 '>    __pyx_t_4 = __pyx_v_i;\n",
       "    __pyx_t_5 = -1;\n",
       "    if (__pyx_t_4 &lt; 0) {\n",
       "      __pyx_t_4 += __pyx_pybuffernd_p_x.diminfo[0].shape;\n",
       "      if (unlikely(__pyx_t_4 &lt; 0)) __pyx_t_5 = 0;\n",
       "    } else if (unlikely(__pyx_t_4 &gt;= __pyx_pybuffernd_p_x.diminfo[0].shape)) __pyx_t_5 = 0;\n",
       "    if (unlikely(__pyx_t_5 != -1)) {\n",
       "      <span class='pyx_c_api'>__Pyx_RaiseBufferIndexError</span>(__pyx_t_5);\n",
       "      <span class='error_goto'>__PYX_ERR(0, 10, __pyx_L1_error)</span>\n",
       "    }\n",
       "    __pyx_t_6 = __pyx_v_i;\n",
       "    __pyx_t_5 = -1;\n",
       "    if (__pyx_t_6 &lt; 0) {\n",
       "      __pyx_t_6 += __pyx_pybuffernd_p_x.diminfo[0].shape;\n",
       "      if (unlikely(__pyx_t_6 &lt; 0)) __pyx_t_5 = 0;\n",
       "    } else if (unlikely(__pyx_t_6 &gt;= __pyx_pybuffernd_p_x.diminfo[0].shape)) __pyx_t_5 = 0;\n",
       "    if (unlikely(__pyx_t_5 != -1)) {\n",
       "      <span class='pyx_c_api'>__Pyx_RaiseBufferIndexError</span>(__pyx_t_5);\n",
       "      <span class='error_goto'>__PYX_ERR(0, 10, __pyx_L1_error)</span>\n",
       "    }\n",
       "    __pyx_v_res = (__pyx_v_res + ((*__Pyx_BufPtrStrided1d(double *, __pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer.buf, __pyx_t_4, __pyx_pybuffernd_p_x.diminfo[0].strides)) * log((*__Pyx_BufPtrStrided1d(double *, __pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer.buf, __pyx_t_6, __pyx_pybuffernd_p_x.diminfo[0].strides)))));\n",
       "  }\n",
       "</pre><pre class=\"cython line score-6\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">11</span>:     <span class=\"k\">return</span> <span class=\"o\">-</span><span class=\"n\">res</span></pre>\n",
       "<pre class='cython code score-6 '>  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  __pyx_t_7 = <span class='py_c_api'>PyFloat_FromDouble</span>((-__pyx_v_res));<span class='error_goto'> if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 11, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_7);\n",
       "  __pyx_r = __pyx_t_7;\n",
       "  __pyx_t_7 = 0;\n",
       "  goto __pyx_L0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "\n",
    "cimport numpy as cnp\n",
    "from libc.math cimport log as clog\n",
    "\n",
    "cpdef shannon_entropy_v2(cnp.ndarray[double] p_x):\n",
    "    cdef double res = 0.0\n",
    "    cdef int n = p_x.shape[0]\n",
    "    cdef int i\n",
    "    for i in range(n):\n",
    "        res += p_x[i] * clog(p_x[i])\n",
    "    return -res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.84 µs ± 30.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "shannon_entropy_v2(pmf)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The `cnp.ndarray[double]` syntax\n",
    "\n",
    "The `cnp.ndarray[double]` declares a NumPy array _buffer_ object.  Cython knows how to interact with this array-like object efficiently.  The `double` in square brackets is the (scalar) dtype of the array elements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29.13 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_bc8ac009cdcc24d174eb27127277f354.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       "pre { line-height: 125%; margin: 0; }\n",
       "td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29.13</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-0\">&#xA0;<span class=\"\">01</span>: </pre>\n",
       "<pre class=\"cython line score-8\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">02</span>: <span class=\"k\">cimport</span> <span class=\"nn\">cython</span></pre>\n",
       "<pre class='cython code score-8 '>  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyDict_NewPresized</span>(0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_test, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">03</span>: <span class=\"k\">cimport</span> <span class=\"nn\">numpy</span> <span class=\"k\">as</span> <span class=\"nn\">cnp</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">04</span>: <span class=\"k\">from</span> <span class=\"nn\">libc.math</span> <span class=\"k\">cimport</span> <span class=\"n\">log</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">05</span>: </pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">06</span>: <span class=\"nd\">@cython</span><span class=\"o\">.</span><span class=\"n\">boundscheck</span><span class=\"p\">(</span><span class=\"bp\">False</span><span class=\"p\">)</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">07</span>: <span class=\"nd\">@cython</span><span class=\"o\">.</span><span class=\"n\">wraparound</span><span class=\"p\">(</span><span class=\"bp\">False</span><span class=\"p\">)</span></pre>\n",
       "<pre class=\"cython line score-26\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">08</span>: <span class=\"k\">def</span> <span class=\"nf\">shannon_entropy_v3</span><span class=\"p\">(</span><span class=\"n\">cnp</span><span class=\"o\">.</span><span class=\"n\">ndarray</span><span class=\"p\">[</span><span class=\"n\">double</span><span class=\"p\">]</span> <span class=\"n\">p_x</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-26 '>/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_bc8ac009cdcc24d174eb27127277f354_1shannon_entropy_v3(PyObject *__pyx_self, PyObject *__pyx_v_p_x); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_bc8ac009cdcc24d174eb27127277f354_1shannon_entropy_v3 = {\"shannon_entropy_v3\", (PyCFunction)__pyx_pw_46_cython_magic_bc8ac009cdcc24d174eb27127277f354_1shannon_entropy_v3, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_bc8ac009cdcc24d174eb27127277f354_1shannon_entropy_v3(PyObject *__pyx_self, PyObject *__pyx_v_p_x) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_v3 (wrapper)\", 0);\n",
       "  if (unlikely(!<span class='pyx_c_api'>__Pyx_ArgTypeTest</span>(((PyObject *)__pyx_v_p_x), __pyx_ptype_5numpy_ndarray, 1, \"p_x\", 0))) <span class='error_goto'>__PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_bc8ac009cdcc24d174eb27127277f354_shannon_entropy_v3(__pyx_self, ((PyArrayObject *)__pyx_v_p_x));\n",
       "\n",
       "  /* function exit code */\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_bc8ac009cdcc24d174eb27127277f354_shannon_entropy_v3(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_p_x) {\n",
       "  double __pyx_v_res;\n",
       "  int __pyx_v_n;\n",
       "  int __pyx_v_i;\n",
       "  __Pyx_LocalBuf_ND __pyx_pybuffernd_p_x;\n",
       "  __Pyx_Buffer __pyx_pybuffer_p_x;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_v3\", 0);\n",
       "  __pyx_pybuffer_p_x.pybuffer.buf = NULL;\n",
       "  __pyx_pybuffer_p_x.refcount = 0;\n",
       "  __pyx_pybuffernd_p_x.data = NULL;\n",
       "  __pyx_pybuffernd_p_x.rcbuffer = &amp;__pyx_pybuffer_p_x;\n",
       "  {\n",
       "    __Pyx_BufFmt_StackElem __pyx_stack[1];\n",
       "    if (unlikely(<span class='pyx_c_api'>__Pyx_GetBufferAndValidate</span>(&amp;__pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer, (PyObject*)__pyx_v_p_x, &amp;__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) <span class='error_goto'>__PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "  }\n",
       "  __pyx_pybuffernd_p_x.diminfo[0].strides = __pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer.strides[0]; __pyx_pybuffernd_p_x.diminfo[0].shape = __pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer.shape[0];\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_6);\n",
       "  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;\n",
       "    __Pyx_PyThreadState_declare\n",
       "    __Pyx_PyThreadState_assign\n",
       "    <span class='pyx_c_api'>__Pyx_ErrFetch</span>(&amp;__pyx_type, &amp;__pyx_value, &amp;__pyx_tb);\n",
       "    <span class='pyx_c_api'>__Pyx_SafeReleaseBuffer</span>(&amp;__pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer);\n",
       "  <span class='pyx_c_api'>__Pyx_ErrRestore</span>(__pyx_type, __pyx_value, __pyx_tb);}\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_bc8ac009cdcc24d174eb27127277f354.shannon_entropy_v3\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  goto __pyx_L2;\n",
       "  __pyx_L0:;\n",
       "  <span class='pyx_c_api'>__Pyx_SafeReleaseBuffer</span>(&amp;__pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer);\n",
       "  __pyx_L2:;\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__8 = <span class='py_c_api'>PyTuple_Pack</span>(4, __pyx_n_s_p_x, __pyx_n_s_res, __pyx_n_s_n, __pyx_n_s_i);<span class='error_goto'> if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple__8);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple__8);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_bc8ac009cdcc24d174eb27127277f354_1shannon_entropy_v3, NULL, __pyx_n_s_cython_magic_bc8ac009cdcc24d174);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_shannon_entropy_v3, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 8, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">09</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">double</span> <span class=\"nf\">res</span> <span class=\"o\">=</span> <span class=\"mf\">0.0</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_res = 0.0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">10</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">n</span> <span class=\"o\">=</span> <span class=\"n\">p_x</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_n = (__pyx_v_p_x-&gt;dimensions[0]);\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">11</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">i</span></pre>\n",
       "<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">12</span>:     <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_t_1 = __pyx_v_n;\n",
       "  __pyx_t_2 = __pyx_t_1;\n",
       "  for (__pyx_t_3 = 0; __pyx_t_3 &lt; __pyx_t_2; __pyx_t_3+=1) {\n",
       "    __pyx_v_i = __pyx_t_3;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">13</span>:         <span class=\"n\">res</span> <span class=\"o\">+=</span> <span class=\"n\">p_x</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">*</span> <span class=\"n\">log</span><span class=\"p\">(</span><span class=\"n\">p_x</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">])</span></pre>\n",
       "<pre class='cython code score-0 '>    __pyx_t_4 = __pyx_v_i;\n",
       "    __pyx_t_5 = __pyx_v_i;\n",
       "    __pyx_v_res = (__pyx_v_res + ((*__Pyx_BufPtrStrided1d(double *, __pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer.buf, __pyx_t_4, __pyx_pybuffernd_p_x.diminfo[0].strides)) * log((*__Pyx_BufPtrStrided1d(double *, __pyx_pybuffernd_p_x.rcbuffer-&gt;pybuffer.buf, __pyx_t_5, __pyx_pybuffernd_p_x.diminfo[0].strides)))));\n",
       "  }\n",
       "</pre><pre class=\"cython line score-6\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">14</span>:     <span class=\"k\">return</span> <span class=\"o\">-</span><span class=\"n\">res</span></pre>\n",
       "<pre class='cython code score-6 '>  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  __pyx_t_6 = <span class='py_c_api'>PyFloat_FromDouble</span>((-__pyx_v_res));<span class='error_goto'> if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 14, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_6);\n",
       "  __pyx_r = __pyx_t_6;\n",
       "  __pyx_t_6 = 0;\n",
       "  goto __pyx_L0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "\n",
    "cimport cython\n",
    "cimport numpy as cnp\n",
    "from libc.math cimport log\n",
    "\n",
    "@cython.boundscheck(False)\n",
    "@cython.wraparound(False)\n",
    "cpdef shannon_entropy_v3(cnp.ndarray[double] p_x):\n",
    "    cdef double res = 0.0\n",
    "    cdef int n = p_x.shape[0]\n",
    "    cdef int i\n",
    "    for i in range(n):\n",
    "        res += p_x[i] * log(p_x[i])\n",
    "    return -res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.91 µs ± 121 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "shannon_entropy_v3(pmf)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The `cython` cimported magic module\n",
    "\n",
    "Cython allows us to control its compile-time semantics and behavior via the magic `cython` module that we `cimport`.\n",
    "\n",
    "We can then use Cython directives like:\n",
    "\n",
    "```python\n",
    "@cython.boundscheck(False)\n",
    "@cython.wraparound(False)\n",
    "def func(...):\n",
    "  ...\n",
    "```\n",
    "\n",
    "To control how code is generated.\n",
    "\n",
    "In this case, we're telling cython to not generate code that does boundschecking or wraparound checking (negative indexing)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Typed memoryview syntax"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!DOCTYPE html>\n",
       "<!-- Generated by Cython 0.29.21 -->\n",
       "<html>\n",
       "<head>\n",
       "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n",
       "    <title>Cython: _cython_magic_213d5a090f2cc61e58c6c2a022d1a128.pyx</title>\n",
       "    <style type=\"text/css\">\n",
       "    \n",
       "body.cython { font-family: courier; font-size: 12; }\n",
       "\n",
       ".cython.tag  {  }\n",
       ".cython.line { margin: 0em }\n",
       ".cython.code { font-size: 9; color: #444444; display: none; margin: 0px 0px 0px 8px; border-left: 8px none; }\n",
       "\n",
       ".cython.line .run { background-color: #B0FFB0; }\n",
       ".cython.line .mis { background-color: #FFB0B0; }\n",
       ".cython.code.run  { border-left: 8px solid #B0FFB0; }\n",
       ".cython.code.mis  { border-left: 8px solid #FFB0B0; }\n",
       "\n",
       ".cython.code .py_c_api  { color: red; }\n",
       ".cython.code .py_macro_api  { color: #FF7000; }\n",
       ".cython.code .pyx_c_api  { color: #FF3000; }\n",
       ".cython.code .pyx_macro_api  { color: #FF7000; }\n",
       ".cython.code .refnanny  { color: #FFA000; }\n",
       ".cython.code .trace  { color: #FFA000; }\n",
       ".cython.code .error_goto  { color: #FFA000; }\n",
       "\n",
       ".cython.code .coerce  { color: #008000; border: 1px dotted #008000 }\n",
       ".cython.code .py_attr { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_attr  { color: #0000FF; }\n",
       ".cython.code .py_call { color: #FF0000; font-weight: bold; }\n",
       ".cython.code .c_call  { color: #0000FF; }\n",
       "\n",
       ".cython.score-0 {background-color: #FFFFff;}\n",
       ".cython.score-1 {background-color: #FFFFe7;}\n",
       ".cython.score-2 {background-color: #FFFFd4;}\n",
       ".cython.score-3 {background-color: #FFFFc4;}\n",
       ".cython.score-4 {background-color: #FFFFb6;}\n",
       ".cython.score-5 {background-color: #FFFFaa;}\n",
       ".cython.score-6 {background-color: #FFFF9f;}\n",
       ".cython.score-7 {background-color: #FFFF96;}\n",
       ".cython.score-8 {background-color: #FFFF8d;}\n",
       ".cython.score-9 {background-color: #FFFF86;}\n",
       ".cython.score-10 {background-color: #FFFF7f;}\n",
       ".cython.score-11 {background-color: #FFFF79;}\n",
       ".cython.score-12 {background-color: #FFFF73;}\n",
       ".cython.score-13 {background-color: #FFFF6e;}\n",
       ".cython.score-14 {background-color: #FFFF6a;}\n",
       ".cython.score-15 {background-color: #FFFF66;}\n",
       ".cython.score-16 {background-color: #FFFF62;}\n",
       ".cython.score-17 {background-color: #FFFF5e;}\n",
       ".cython.score-18 {background-color: #FFFF5b;}\n",
       ".cython.score-19 {background-color: #FFFF57;}\n",
       ".cython.score-20 {background-color: #FFFF55;}\n",
       ".cython.score-21 {background-color: #FFFF52;}\n",
       ".cython.score-22 {background-color: #FFFF4f;}\n",
       ".cython.score-23 {background-color: #FFFF4d;}\n",
       ".cython.score-24 {background-color: #FFFF4b;}\n",
       ".cython.score-25 {background-color: #FFFF48;}\n",
       ".cython.score-26 {background-color: #FFFF46;}\n",
       ".cython.score-27 {background-color: #FFFF44;}\n",
       ".cython.score-28 {background-color: #FFFF43;}\n",
       ".cython.score-29 {background-color: #FFFF41;}\n",
       ".cython.score-30 {background-color: #FFFF3f;}\n",
       ".cython.score-31 {background-color: #FFFF3e;}\n",
       ".cython.score-32 {background-color: #FFFF3c;}\n",
       ".cython.score-33 {background-color: #FFFF3b;}\n",
       ".cython.score-34 {background-color: #FFFF39;}\n",
       ".cython.score-35 {background-color: #FFFF38;}\n",
       ".cython.score-36 {background-color: #FFFF37;}\n",
       ".cython.score-37 {background-color: #FFFF36;}\n",
       ".cython.score-38 {background-color: #FFFF35;}\n",
       ".cython.score-39 {background-color: #FFFF34;}\n",
       ".cython.score-40 {background-color: #FFFF33;}\n",
       ".cython.score-41 {background-color: #FFFF32;}\n",
       ".cython.score-42 {background-color: #FFFF31;}\n",
       ".cython.score-43 {background-color: #FFFF30;}\n",
       ".cython.score-44 {background-color: #FFFF2f;}\n",
       ".cython.score-45 {background-color: #FFFF2e;}\n",
       ".cython.score-46 {background-color: #FFFF2d;}\n",
       ".cython.score-47 {background-color: #FFFF2c;}\n",
       ".cython.score-48 {background-color: #FFFF2b;}\n",
       ".cython.score-49 {background-color: #FFFF2b;}\n",
       ".cython.score-50 {background-color: #FFFF2a;}\n",
       ".cython.score-51 {background-color: #FFFF29;}\n",
       ".cython.score-52 {background-color: #FFFF29;}\n",
       ".cython.score-53 {background-color: #FFFF28;}\n",
       ".cython.score-54 {background-color: #FFFF27;}\n",
       ".cython.score-55 {background-color: #FFFF27;}\n",
       ".cython.score-56 {background-color: #FFFF26;}\n",
       ".cython.score-57 {background-color: #FFFF26;}\n",
       ".cython.score-58 {background-color: #FFFF25;}\n",
       ".cython.score-59 {background-color: #FFFF24;}\n",
       ".cython.score-60 {background-color: #FFFF24;}\n",
       ".cython.score-61 {background-color: #FFFF23;}\n",
       ".cython.score-62 {background-color: #FFFF23;}\n",
       ".cython.score-63 {background-color: #FFFF22;}\n",
       ".cython.score-64 {background-color: #FFFF22;}\n",
       ".cython.score-65 {background-color: #FFFF22;}\n",
       ".cython.score-66 {background-color: #FFFF21;}\n",
       ".cython.score-67 {background-color: #FFFF21;}\n",
       ".cython.score-68 {background-color: #FFFF20;}\n",
       ".cython.score-69 {background-color: #FFFF20;}\n",
       ".cython.score-70 {background-color: #FFFF1f;}\n",
       ".cython.score-71 {background-color: #FFFF1f;}\n",
       ".cython.score-72 {background-color: #FFFF1f;}\n",
       ".cython.score-73 {background-color: #FFFF1e;}\n",
       ".cython.score-74 {background-color: #FFFF1e;}\n",
       ".cython.score-75 {background-color: #FFFF1e;}\n",
       ".cython.score-76 {background-color: #FFFF1d;}\n",
       ".cython.score-77 {background-color: #FFFF1d;}\n",
       ".cython.score-78 {background-color: #FFFF1c;}\n",
       ".cython.score-79 {background-color: #FFFF1c;}\n",
       ".cython.score-80 {background-color: #FFFF1c;}\n",
       ".cython.score-81 {background-color: #FFFF1c;}\n",
       ".cython.score-82 {background-color: #FFFF1b;}\n",
       ".cython.score-83 {background-color: #FFFF1b;}\n",
       ".cython.score-84 {background-color: #FFFF1b;}\n",
       ".cython.score-85 {background-color: #FFFF1a;}\n",
       ".cython.score-86 {background-color: #FFFF1a;}\n",
       ".cython.score-87 {background-color: #FFFF1a;}\n",
       ".cython.score-88 {background-color: #FFFF1a;}\n",
       ".cython.score-89 {background-color: #FFFF19;}\n",
       ".cython.score-90 {background-color: #FFFF19;}\n",
       ".cython.score-91 {background-color: #FFFF19;}\n",
       ".cython.score-92 {background-color: #FFFF19;}\n",
       ".cython.score-93 {background-color: #FFFF18;}\n",
       ".cython.score-94 {background-color: #FFFF18;}\n",
       ".cython.score-95 {background-color: #FFFF18;}\n",
       ".cython.score-96 {background-color: #FFFF18;}\n",
       ".cython.score-97 {background-color: #FFFF17;}\n",
       ".cython.score-98 {background-color: #FFFF17;}\n",
       ".cython.score-99 {background-color: #FFFF17;}\n",
       ".cython.score-100 {background-color: #FFFF17;}\n",
       ".cython.score-101 {background-color: #FFFF16;}\n",
       ".cython.score-102 {background-color: #FFFF16;}\n",
       ".cython.score-103 {background-color: #FFFF16;}\n",
       ".cython.score-104 {background-color: #FFFF16;}\n",
       ".cython.score-105 {background-color: #FFFF16;}\n",
       ".cython.score-106 {background-color: #FFFF15;}\n",
       ".cython.score-107 {background-color: #FFFF15;}\n",
       ".cython.score-108 {background-color: #FFFF15;}\n",
       ".cython.score-109 {background-color: #FFFF15;}\n",
       ".cython.score-110 {background-color: #FFFF15;}\n",
       ".cython.score-111 {background-color: #FFFF15;}\n",
       ".cython.score-112 {background-color: #FFFF14;}\n",
       ".cython.score-113 {background-color: #FFFF14;}\n",
       ".cython.score-114 {background-color: #FFFF14;}\n",
       ".cython.score-115 {background-color: #FFFF14;}\n",
       ".cython.score-116 {background-color: #FFFF14;}\n",
       ".cython.score-117 {background-color: #FFFF14;}\n",
       ".cython.score-118 {background-color: #FFFF13;}\n",
       ".cython.score-119 {background-color: #FFFF13;}\n",
       ".cython.score-120 {background-color: #FFFF13;}\n",
       ".cython.score-121 {background-color: #FFFF13;}\n",
       ".cython.score-122 {background-color: #FFFF13;}\n",
       ".cython.score-123 {background-color: #FFFF13;}\n",
       ".cython.score-124 {background-color: #FFFF13;}\n",
       ".cython.score-125 {background-color: #FFFF12;}\n",
       ".cython.score-126 {background-color: #FFFF12;}\n",
       ".cython.score-127 {background-color: #FFFF12;}\n",
       ".cython.score-128 {background-color: #FFFF12;}\n",
       ".cython.score-129 {background-color: #FFFF12;}\n",
       ".cython.score-130 {background-color: #FFFF12;}\n",
       ".cython.score-131 {background-color: #FFFF12;}\n",
       ".cython.score-132 {background-color: #FFFF11;}\n",
       ".cython.score-133 {background-color: #FFFF11;}\n",
       ".cython.score-134 {background-color: #FFFF11;}\n",
       ".cython.score-135 {background-color: #FFFF11;}\n",
       ".cython.score-136 {background-color: #FFFF11;}\n",
       ".cython.score-137 {background-color: #FFFF11;}\n",
       ".cython.score-138 {background-color: #FFFF11;}\n",
       ".cython.score-139 {background-color: #FFFF11;}\n",
       ".cython.score-140 {background-color: #FFFF11;}\n",
       ".cython.score-141 {background-color: #FFFF10;}\n",
       ".cython.score-142 {background-color: #FFFF10;}\n",
       ".cython.score-143 {background-color: #FFFF10;}\n",
       ".cython.score-144 {background-color: #FFFF10;}\n",
       ".cython.score-145 {background-color: #FFFF10;}\n",
       ".cython.score-146 {background-color: #FFFF10;}\n",
       ".cython.score-147 {background-color: #FFFF10;}\n",
       ".cython.score-148 {background-color: #FFFF10;}\n",
       ".cython.score-149 {background-color: #FFFF10;}\n",
       ".cython.score-150 {background-color: #FFFF0f;}\n",
       ".cython.score-151 {background-color: #FFFF0f;}\n",
       ".cython.score-152 {background-color: #FFFF0f;}\n",
       ".cython.score-153 {background-color: #FFFF0f;}\n",
       ".cython.score-154 {background-color: #FFFF0f;}\n",
       ".cython.score-155 {background-color: #FFFF0f;}\n",
       ".cython.score-156 {background-color: #FFFF0f;}\n",
       ".cython.score-157 {background-color: #FFFF0f;}\n",
       ".cython.score-158 {background-color: #FFFF0f;}\n",
       ".cython.score-159 {background-color: #FFFF0f;}\n",
       ".cython.score-160 {background-color: #FFFF0f;}\n",
       ".cython.score-161 {background-color: #FFFF0e;}\n",
       ".cython.score-162 {background-color: #FFFF0e;}\n",
       ".cython.score-163 {background-color: #FFFF0e;}\n",
       ".cython.score-164 {background-color: #FFFF0e;}\n",
       ".cython.score-165 {background-color: #FFFF0e;}\n",
       ".cython.score-166 {background-color: #FFFF0e;}\n",
       ".cython.score-167 {background-color: #FFFF0e;}\n",
       ".cython.score-168 {background-color: #FFFF0e;}\n",
       ".cython.score-169 {background-color: #FFFF0e;}\n",
       ".cython.score-170 {background-color: #FFFF0e;}\n",
       ".cython.score-171 {background-color: #FFFF0e;}\n",
       ".cython.score-172 {background-color: #FFFF0e;}\n",
       ".cython.score-173 {background-color: #FFFF0d;}\n",
       ".cython.score-174 {background-color: #FFFF0d;}\n",
       ".cython.score-175 {background-color: #FFFF0d;}\n",
       ".cython.score-176 {background-color: #FFFF0d;}\n",
       ".cython.score-177 {background-color: #FFFF0d;}\n",
       ".cython.score-178 {background-color: #FFFF0d;}\n",
       ".cython.score-179 {background-color: #FFFF0d;}\n",
       ".cython.score-180 {background-color: #FFFF0d;}\n",
       ".cython.score-181 {background-color: #FFFF0d;}\n",
       ".cython.score-182 {background-color: #FFFF0d;}\n",
       ".cython.score-183 {background-color: #FFFF0d;}\n",
       ".cython.score-184 {background-color: #FFFF0d;}\n",
       ".cython.score-185 {background-color: #FFFF0d;}\n",
       ".cython.score-186 {background-color: #FFFF0d;}\n",
       ".cython.score-187 {background-color: #FFFF0c;}\n",
       ".cython.score-188 {background-color: #FFFF0c;}\n",
       ".cython.score-189 {background-color: #FFFF0c;}\n",
       ".cython.score-190 {background-color: #FFFF0c;}\n",
       ".cython.score-191 {background-color: #FFFF0c;}\n",
       ".cython.score-192 {background-color: #FFFF0c;}\n",
       ".cython.score-193 {background-color: #FFFF0c;}\n",
       ".cython.score-194 {background-color: #FFFF0c;}\n",
       ".cython.score-195 {background-color: #FFFF0c;}\n",
       ".cython.score-196 {background-color: #FFFF0c;}\n",
       ".cython.score-197 {background-color: #FFFF0c;}\n",
       ".cython.score-198 {background-color: #FFFF0c;}\n",
       ".cython.score-199 {background-color: #FFFF0c;}\n",
       ".cython.score-200 {background-color: #FFFF0c;}\n",
       ".cython.score-201 {background-color: #FFFF0c;}\n",
       ".cython.score-202 {background-color: #FFFF0c;}\n",
       ".cython.score-203 {background-color: #FFFF0b;}\n",
       ".cython.score-204 {background-color: #FFFF0b;}\n",
       ".cython.score-205 {background-color: #FFFF0b;}\n",
       ".cython.score-206 {background-color: #FFFF0b;}\n",
       ".cython.score-207 {background-color: #FFFF0b;}\n",
       ".cython.score-208 {background-color: #FFFF0b;}\n",
       ".cython.score-209 {background-color: #FFFF0b;}\n",
       ".cython.score-210 {background-color: #FFFF0b;}\n",
       ".cython.score-211 {background-color: #FFFF0b;}\n",
       ".cython.score-212 {background-color: #FFFF0b;}\n",
       ".cython.score-213 {background-color: #FFFF0b;}\n",
       ".cython.score-214 {background-color: #FFFF0b;}\n",
       ".cython.score-215 {background-color: #FFFF0b;}\n",
       ".cython.score-216 {background-color: #FFFF0b;}\n",
       ".cython.score-217 {background-color: #FFFF0b;}\n",
       ".cython.score-218 {background-color: #FFFF0b;}\n",
       ".cython.score-219 {background-color: #FFFF0b;}\n",
       ".cython.score-220 {background-color: #FFFF0b;}\n",
       ".cython.score-221 {background-color: #FFFF0b;}\n",
       ".cython.score-222 {background-color: #FFFF0a;}\n",
       ".cython.score-223 {background-color: #FFFF0a;}\n",
       ".cython.score-224 {background-color: #FFFF0a;}\n",
       ".cython.score-225 {background-color: #FFFF0a;}\n",
       ".cython.score-226 {background-color: #FFFF0a;}\n",
       ".cython.score-227 {background-color: #FFFF0a;}\n",
       ".cython.score-228 {background-color: #FFFF0a;}\n",
       ".cython.score-229 {background-color: #FFFF0a;}\n",
       ".cython.score-230 {background-color: #FFFF0a;}\n",
       ".cython.score-231 {background-color: #FFFF0a;}\n",
       ".cython.score-232 {background-color: #FFFF0a;}\n",
       ".cython.score-233 {background-color: #FFFF0a;}\n",
       ".cython.score-234 {background-color: #FFFF0a;}\n",
       ".cython.score-235 {background-color: #FFFF0a;}\n",
       ".cython.score-236 {background-color: #FFFF0a;}\n",
       ".cython.score-237 {background-color: #FFFF0a;}\n",
       ".cython.score-238 {background-color: #FFFF0a;}\n",
       ".cython.score-239 {background-color: #FFFF0a;}\n",
       ".cython.score-240 {background-color: #FFFF0a;}\n",
       ".cython.score-241 {background-color: #FFFF0a;}\n",
       ".cython.score-242 {background-color: #FFFF0a;}\n",
       ".cython.score-243 {background-color: #FFFF0a;}\n",
       ".cython.score-244 {background-color: #FFFF0a;}\n",
       ".cython.score-245 {background-color: #FFFF0a;}\n",
       ".cython.score-246 {background-color: #FFFF09;}\n",
       ".cython.score-247 {background-color: #FFFF09;}\n",
       ".cython.score-248 {background-color: #FFFF09;}\n",
       ".cython.score-249 {background-color: #FFFF09;}\n",
       ".cython.score-250 {background-color: #FFFF09;}\n",
       ".cython.score-251 {background-color: #FFFF09;}\n",
       ".cython.score-252 {background-color: #FFFF09;}\n",
       ".cython.score-253 {background-color: #FFFF09;}\n",
       ".cython.score-254 {background-color: #FFFF09;}\n",
       "pre { line-height: 125%; margin: 0; }\n",
       "td.linenos pre { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos { color: #000000; background-color: #f0f0f0; padding-left: 5px; padding-right: 5px; }\n",
       "td.linenos pre.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       "span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n",
       ".cython .hll { background-color: #ffffcc }\n",
       ".cython { background: #f8f8f8; }\n",
       ".cython .c { color: #408080; font-style: italic } /* Comment */\n",
       ".cython .err { border: 1px solid #FF0000 } /* Error */\n",
       ".cython .k { color: #008000; font-weight: bold } /* Keyword */\n",
       ".cython .o { color: #666666 } /* Operator */\n",
       ".cython .ch { color: #408080; font-style: italic } /* Comment.Hashbang */\n",
       ".cython .cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
       ".cython .cp { color: #BC7A00 } /* Comment.Preproc */\n",
       ".cython .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */\n",
       ".cython .c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
       ".cython .cs { color: #408080; font-style: italic } /* Comment.Special */\n",
       ".cython .gd { color: #A00000 } /* Generic.Deleted */\n",
       ".cython .ge { font-style: italic } /* Generic.Emph */\n",
       ".cython .gr { color: #FF0000 } /* Generic.Error */\n",
       ".cython .gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
       ".cython .gi { color: #00A000 } /* Generic.Inserted */\n",
       ".cython .go { color: #888888 } /* Generic.Output */\n",
       ".cython .gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
       ".cython .gs { font-weight: bold } /* Generic.Strong */\n",
       ".cython .gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
       ".cython .gt { color: #0044DD } /* Generic.Traceback */\n",
       ".cython .kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
       ".cython .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
       ".cython .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
       ".cython .kp { color: #008000 } /* Keyword.Pseudo */\n",
       ".cython .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
       ".cython .kt { color: #B00040 } /* Keyword.Type */\n",
       ".cython .m { color: #666666 } /* Literal.Number */\n",
       ".cython .s { color: #BA2121 } /* Literal.String */\n",
       ".cython .na { color: #7D9029 } /* Name.Attribute */\n",
       ".cython .nb { color: #008000 } /* Name.Builtin */\n",
       ".cython .nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
       ".cython .no { color: #880000 } /* Name.Constant */\n",
       ".cython .nd { color: #AA22FF } /* Name.Decorator */\n",
       ".cython .ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
       ".cython .ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
       ".cython .nf { color: #0000FF } /* Name.Function */\n",
       ".cython .nl { color: #A0A000 } /* Name.Label */\n",
       ".cython .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
       ".cython .nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
       ".cython .nv { color: #19177C } /* Name.Variable */\n",
       ".cython .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
       ".cython .w { color: #bbbbbb } /* Text.Whitespace */\n",
       ".cython .mb { color: #666666 } /* Literal.Number.Bin */\n",
       ".cython .mf { color: #666666 } /* Literal.Number.Float */\n",
       ".cython .mh { color: #666666 } /* Literal.Number.Hex */\n",
       ".cython .mi { color: #666666 } /* Literal.Number.Integer */\n",
       ".cython .mo { color: #666666 } /* Literal.Number.Oct */\n",
       ".cython .sa { color: #BA2121 } /* Literal.String.Affix */\n",
       ".cython .sb { color: #BA2121 } /* Literal.String.Backtick */\n",
       ".cython .sc { color: #BA2121 } /* Literal.String.Char */\n",
       ".cython .dl { color: #BA2121 } /* Literal.String.Delimiter */\n",
       ".cython .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
       ".cython .s2 { color: #BA2121 } /* Literal.String.Double */\n",
       ".cython .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
       ".cython .sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
       ".cython .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
       ".cython .sx { color: #008000 } /* Literal.String.Other */\n",
       ".cython .sr { color: #BB6688 } /* Literal.String.Regex */\n",
       ".cython .s1 { color: #BA2121 } /* Literal.String.Single */\n",
       ".cython .ss { color: #19177C } /* Literal.String.Symbol */\n",
       ".cython .bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
       ".cython .fm { color: #0000FF } /* Name.Function.Magic */\n",
       ".cython .vc { color: #19177C } /* Name.Variable.Class */\n",
       ".cython .vg { color: #19177C } /* Name.Variable.Global */\n",
       ".cython .vi { color: #19177C } /* Name.Variable.Instance */\n",
       ".cython .vm { color: #19177C } /* Name.Variable.Magic */\n",
       ".cython .il { color: #666666 } /* Literal.Number.Integer.Long */\n",
       "    </style>\n",
       "</head>\n",
       "<body class=\"cython\">\n",
       "<p><span style=\"border-bottom: solid 1px grey;\">Generated by Cython 0.29.21</span></p>\n",
       "<p>\n",
       "    <span style=\"background-color: #FFFF00\">Yellow lines</span> hint at Python interaction.<br />\n",
       "    Click on a line that starts with a \"<code>+</code>\" to see the C code that Cython generated for it.\n",
       "</p>\n",
       "<div class=\"cython\"><pre class=\"cython line score-0\">&#xA0;<span class=\"\">01</span>: </pre>\n",
       "<pre class=\"cython line score-8\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">02</span>: <span class=\"k\">cimport</span> <span class=\"nn\">cython</span></pre>\n",
       "<pre class='cython code score-8 '>  __pyx_t_1 = <span class='pyx_c_api'>__Pyx_PyDict_NewPresized</span>(0);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_test, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 2, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">03</span>: <span class=\"k\">from</span> <span class=\"nn\">libc.math</span> <span class=\"k\">cimport</span> <span class=\"n\">log</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">04</span>: </pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">05</span>: <span class=\"nd\">@cython</span><span class=\"o\">.</span><span class=\"n\">boundscheck</span><span class=\"p\">(</span><span class=\"bp\">False</span><span class=\"p\">)</span></pre>\n",
       "<pre class=\"cython line score-0\">&#xA0;<span class=\"\">06</span>: <span class=\"nd\">@cython</span><span class=\"o\">.</span><span class=\"n\">wraparound</span><span class=\"p\">(</span><span class=\"bp\">False</span><span class=\"p\">)</span></pre>\n",
       "<pre class=\"cython line score-20\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">07</span>: <span class=\"k\">def</span> <span class=\"nf\">shannon_entropy_mv</span><span class=\"p\">(</span><span class=\"n\">double</span><span class=\"p\">[::</span><span class=\"mf\">1</span><span class=\"p\">]</span> <span class=\"n\">p_x</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-20 '>/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_213d5a090f2cc61e58c6c2a022d1a128_1shannon_entropy_mv(PyObject *__pyx_self, PyObject *__pyx_arg_p_x); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_213d5a090f2cc61e58c6c2a022d1a128_1shannon_entropy_mv = {\"shannon_entropy_mv\", (PyCFunction)__pyx_pw_46_cython_magic_213d5a090f2cc61e58c6c2a022d1a128_1shannon_entropy_mv, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_213d5a090f2cc61e58c6c2a022d1a128_1shannon_entropy_mv(PyObject *__pyx_self, PyObject *__pyx_arg_p_x) {\n",
       "  __Pyx_memviewslice __pyx_v_p_x = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  PyObject *__pyx_r = 0;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_mv (wrapper)\", 0);\n",
       "  assert(__pyx_arg_p_x); {\n",
       "    __pyx_v_p_x = <span class='pyx_c_api'>__Pyx_PyObject_to_MemoryviewSlice_dc_double</span>(__pyx_arg_p_x, PyBUF_WRITABLE);<span class='error_goto'> if (unlikely(!__pyx_v_p_x.memview)) __PYX_ERR(0, 7, __pyx_L3_error)</span>\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L3_error:;\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_213d5a090f2cc61e58c6c2a022d1a128.shannon_entropy_mv\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_213d5a090f2cc61e58c6c2a022d1a128_shannon_entropy_mv(__pyx_self, __pyx_v_p_x);\n",
       "  int __pyx_lineno = 0;\n",
       "  const char *__pyx_filename = NULL;\n",
       "  int __pyx_clineno = 0;\n",
       "\n",
       "  /* function exit code */\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_213d5a090f2cc61e58c6c2a022d1a128_shannon_entropy_mv(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_p_x) {\n",
       "  double __pyx_v_res;\n",
       "  int __pyx_v_n;\n",
       "  int __pyx_v_i;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  <span class='refnanny'>__Pyx_RefNannyDeclarations</span>\n",
       "  <span class='refnanny'>__Pyx_RefNannySetupContext</span>(\"shannon_entropy_mv\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_t_6);\n",
       "  <span class='pyx_c_api'>__Pyx_AddTraceback</span>(\"_cython_magic_213d5a090f2cc61e58c6c2a022d1a128.shannon_entropy_mv\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __PYX_XDEC_MEMVIEW(&amp;__pyx_v_p_x, 1);\n",
       "  <span class='refnanny'>__Pyx_XGIVEREF</span>(__pyx_r);\n",
       "  <span class='refnanny'>__Pyx_RefNannyFinishContext</span>();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__19 = <span class='py_c_api'>PyTuple_Pack</span>(5, __pyx_n_s_p_x, __pyx_n_s_p_x, __pyx_n_s_res, __pyx_n_s_n, __pyx_n_s_i);<span class='error_goto'> if (unlikely(!__pyx_tuple__19)) __PYX_ERR(0, 7, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_tuple__19);\n",
       "  <span class='refnanny'>__Pyx_GIVEREF</span>(__pyx_tuple__19);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&amp;__pyx_mdef_46_cython_magic_213d5a090f2cc61e58c6c2a022d1a128_1shannon_entropy_mv, NULL, __pyx_n_s_cython_magic_213d5a090f2cc61e58);<span class='error_goto'> if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_1);\n",
       "  if (<span class='py_c_api'>PyDict_SetItem</span>(__pyx_d, __pyx_n_s_shannon_entropy_mv, __pyx_t_1) &lt; 0) <span class='error_goto'>__PYX_ERR(0, 7, __pyx_L1_error)</span>\n",
       "  <span class='pyx_macro_api'>__Pyx_DECREF</span>(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_codeobj__20 = (PyObject*)<span class='pyx_c_api'>__Pyx_PyCode_New</span>(1, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__19, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_sugang_cache_ipython_cytho, __pyx_n_s_shannon_entropy_mv, 7, __pyx_empty_bytes);<span class='error_goto'> if (unlikely(!__pyx_codeobj__20)) __PYX_ERR(0, 7, __pyx_L1_error)</span>\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">08</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">double</span> <span class=\"nf\">res</span> <span class=\"o\">=</span> <span class=\"mf\">0.0</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_res = 0.0;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">09</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">n</span> <span class=\"o\">=</span> <span class=\"n\">p_x</span><span class=\"o\">.</span><span class=\"n\">shape</span><span class=\"p\">[</span><span class=\"mf\">0</span><span class=\"p\">]</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_v_n = (__pyx_v_p_x.shape[0]);\n",
       "</pre><pre class=\"cython line score-0\">&#xA0;<span class=\"\">10</span>:     <span class=\"k\">cdef</span> <span class=\"kt\">int</span> <span class=\"nf\">i</span></pre>\n",
       "<pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">11</span>:     <span class=\"k\">for</span> <span class=\"n\">i</span> <span class=\"ow\">in</span> <span class=\"nb\">range</span><span class=\"p\">(</span><span class=\"n\">n</span><span class=\"p\">):</span></pre>\n",
       "<pre class='cython code score-0 '>  __pyx_t_1 = __pyx_v_n;\n",
       "  __pyx_t_2 = __pyx_t_1;\n",
       "  for (__pyx_t_3 = 0; __pyx_t_3 &lt; __pyx_t_2; __pyx_t_3+=1) {\n",
       "    __pyx_v_i = __pyx_t_3;\n",
       "</pre><pre class=\"cython line score-0\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">12</span>:         <span class=\"n\">res</span> <span class=\"o\">+=</span> <span class=\"n\">p_x</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">]</span> <span class=\"o\">*</span> <span class=\"n\">log</span><span class=\"p\">(</span><span class=\"n\">p_x</span><span class=\"p\">[</span><span class=\"n\">i</span><span class=\"p\">])</span></pre>\n",
       "<pre class='cython code score-0 '>    __pyx_t_4 = __pyx_v_i;\n",
       "    __pyx_t_5 = __pyx_v_i;\n",
       "    __pyx_v_res = (__pyx_v_res + ((*((double *) ( /* dim=0 */ ((char *) (((double *) __pyx_v_p_x.data) + __pyx_t_4)) ))) * log((*((double *) ( /* dim=0 */ ((char *) (((double *) __pyx_v_p_x.data) + __pyx_t_5)) ))))));\n",
       "  }\n",
       "</pre><pre class=\"cython line score-6\" onclick=\"(function(s){s.display=s.display==='block'?'none':'block'})(this.nextElementSibling.style)\">+<span class=\"\">13</span>:     <span class=\"k\">return</span> <span class=\"o\">-</span><span class=\"n\">res</span></pre>\n",
       "<pre class='cython code score-6 '>  <span class='pyx_macro_api'>__Pyx_XDECREF</span>(__pyx_r);\n",
       "  __pyx_t_6 = <span class='py_c_api'>PyFloat_FromDouble</span>((-__pyx_v_res));<span class='error_goto'> if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 13, __pyx_L1_error)</span>\n",
       "  <span class='refnanny'>__Pyx_GOTREF</span>(__pyx_t_6);\n",
       "  __pyx_r = __pyx_t_6;\n",
       "  __pyx_t_6 = 0;\n",
       "  goto __pyx_L0;\n",
       "</pre></div></body></html>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%%cython -a\n",
    "\n",
    "cimport cython\n",
    "from libc.math cimport log\n",
    "\n",
    "@cython.boundscheck(False)\n",
    "@cython.wraparound(False)\n",
    "def shannon_entropy_mv(double[::1] p_x):\n",
    "    cdef double res = 0.0\n",
    "    cdef int n = p_x.shape[0]\n",
    "    cdef int i\n",
    "    for i in range(n):\n",
    "        res += p_x[i] * log(p_x[i])\n",
    "    return -res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.18 µs ± 7.55 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "shannon_entropy_mv(pmf)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### A big BUT\n",
    "\n",
    "However, not all numpy array can be passed from/to cython without any trouble. The storage of a normal numpy array is NOT necessarily contiguous. Therefore we often need the following copy operation. \n",
    "\n",
    "Note that the following code will not compile since we need to "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "Error compiling Cython file:\n",
      "------------------------------------------------------------\n",
      "...\n",
      "import numpy as np\n",
      "# cimport numpy as np\n",
      "\n",
      "matrix = np.random.randn(10000, 2)\n",
      "\n",
      "cdef np.ndarray[double, ndim=2, mode='fortran'] arg = np.asfortranarray(matrix, dtype=np.float64)\n",
      "    ^\n",
      "------------------------------------------------------------\n",
      "\n",
      "/home/user/.cache/ipython/cython/_cython_magic_75cadbb9976b9f5487cb28715a333baa.pyx:6:5: 'np' is not a cimported module\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "object of type 'NoneType' has no len()",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-33-4d6f9605f521>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_cell_magic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'cython'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"import numpy as np\\n# cimport numpy as np\\n\\nmatrix = np.random.randn(10000, 2)\\n\\ncdef np.ndarray[double, ndim=2, mode='fortran'] arg = np.asfortranarray(matrix, dtype=np.float64)\\n\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/IPython/core/interactiveshell.py\u001b[0m in \u001b[0;36mrun_cell_magic\u001b[0;34m(self, magic_name, line, cell)\u001b[0m\n\u001b[1;32m   2357\u001b[0m             \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuiltin_trap\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2358\u001b[0m                 \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mmagic_arg_s\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2359\u001b[0;31m                 \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   2360\u001b[0m             \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2361\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m</home/user/anaconda3/lib/python3.7/site-packages/decorator.py:decorator-gen-128>\u001b[0m in \u001b[0;36mcython\u001b[0;34m(self, line, cell)\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/IPython/core/magic.py\u001b[0m in \u001b[0;36m<lambda>\u001b[0;34m(f, *a, **k)\u001b[0m\n\u001b[1;32m    185\u001b[0m     \u001b[0;31m# but it's overkill for just that one bit of state.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    186\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0mmagic_deco\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 187\u001b[0;31m         \u001b[0mcall\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    188\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    189\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mcallable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/anaconda3/lib/python3.7/site-packages/Cython/Build/IpythonMagic.py\u001b[0m in \u001b[0;36mcython\u001b[0;34m(self, line, cell)\u001b[0m\n\u001b[1;32m    323\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mneed_cythonize\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    324\u001b[0m             \u001b[0mextensions\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_cythonize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodule_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlib_dir\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mquiet\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mquiet\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 325\u001b[0;31m             \u001b[0;32massert\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mextensions\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    326\u001b[0m             \u001b[0mextension\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mextensions\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    327\u001b[0m             \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_code_cache\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodule_name\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: object of type 'NoneType' has no len()"
     ]
    }
   ],
   "source": [
    "%%cython \n",
    "import numpy as np\n",
    "cimport numpy as np\n",
    "\n",
    "matrix = np.random.randn(10000, 2)\n",
    "\n",
    "cdef np.ndarray[double, ndim=2, mode='fortran'] arg = np.asfortranarray(matrix, dtype=np.float64)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
